package com.e1xp.deport_management_system.controller;


import com.e1xp.deport_management_system.entity.User;
import com.e1xp.deport_management_system.exception.CustomException;
import com.e1xp.deport_management_system.exception.CustomExceptionType;
import com.e1xp.deport_management_system.service.IUserService;
import com.e1xp.deport_management_system.utils.AjaxResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author E1xP
 * @since 2021-04-09
 */
@Controller
@RequestMapping("/user")
public class UserController {

    @Resource
    private IUserService userService;

    @Value("${depot.cookieRememberTime}")
    private int cookieRememberTime;

    @Value("${depot.loginTimeGap}")
    private int loginTimeGap;

    /**
     * 用于访问前检查是否已有记住cookie
     *
     * @param response HttpServletResponse
     * @param request  HttpServletRequest
     * @return 若可登录跳转至首页，若无法登录则跳转至登录页面
     */
    @RequestMapping("/preLogin")
    public String preLogin(HttpServletResponse response, HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        String username = null;
        String password = null;
        long timestamp = 0;
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                //从cookie获取账户和密码
                switch (cookie.getName()) {
                    case "username":
                        username = cookie.getValue();
                        continue;
                    case "password":
                        password = cookie.getValue();
                        continue;
                    case "timestamp":
                        timestamp = Long.parseLong(cookie.getValue());
                }
            }

            if (username != null && password != null && !username.isEmpty() && !password.isEmpty()&&timestamp!=0) {
                User user;//尝试登陆
                try {
                    user = userService.login(username, password, timestamp);
                } catch (CustomException e) {
                    return "redirect:/loginPage.html";
                }
                HttpSession session = request.getSession(true);
                session.setAttribute("user", user);//设置session
                session.setAttribute("loginTime", new Date());//设置登陆时间
                session.setAttribute("instanceId",user.getInstanceId());//设置实例id
                return "redirect:/index/frontData";
            }
        }
        return "redirect:/loginPage.html";
    }

    /**
     * 用于处理登录请求
     *
     * @param username 用户名
     * @param password 密码
     * @param remember 是否记住
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     * @return 若成功跳转首页，若失败则刷新页面
     * @throws CustomException 当用户登陆失败时抛出该异常
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public AjaxResponse login(String username, String password,long timestamp, int remember, HttpServletRequest request, HttpServletResponse response) throws CustomException {
        //校验登陆毫秒数时间
        long currentTimeStamp=System.currentTimeMillis();
        if(currentTimeStamp-timestamp>=loginTimeGap){
            throw new CustomException(CustomExceptionType.USER_LOGIN_ERROR);
        }
        User user = userService.login(username, password,timestamp);//尝试登陆
        HttpSession session = request.getSession(true);
        session.setAttribute("user", user);//设置session
        session.setAttribute("loginTime", new Date());//设置登陆时间
        session.setAttribute("instanceId",user.getInstanceId());//设置实例id
        if (remember == 1) {//判断是否记住
            Cookie usernameCookie = new Cookie("username", user.getUsername());
            Cookie passwordCookie = new Cookie("password", password);
            Cookie timestampCookie=new Cookie("timestamp",String.valueOf(timestamp));
            //设置记住时间
            usernameCookie.setMaxAge(cookieRememberTime);
            passwordCookie.setMaxAge(cookieRememberTime);
            timestampCookie.setMaxAge(cookieRememberTime);
            response.addCookie(usernameCookie);
            response.addCookie(passwordCookie);
            response.addCookie(timestampCookie);
        }
        return AjaxResponse.success("登陆成功");
    }

    /**
     * 用于渲染修改密码页面
     * @return ModelAndView
     */
    @RequestMapping("/changePasswordPage")
    public ModelAndView changePasswordPage(){
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("changePassword");
        return  modelAndView;
    }

    /**
     *
     * @param userId 用户id
     * @param oldPassword 旧密码
     * @param newPassword 新密码
     * @return AjaxResponse
     * @throws CustomException 当用户不存在，救密码错误时抛出该异常
     */
    @RequestMapping("/changePassword")
    @ResponseBody
    public AjaxResponse changePassword(long userId,String oldPassword,String newPassword) throws CustomException {
        userService.changePassword(userId,oldPassword,newPassword);
        return AjaxResponse.success();
    }

    /**
     * 用于注销登陆
     * @param request HttpServletRequest
     * @param response HttpServletResponse
     * @return String重定向
     */
    @RequestMapping("/logout")
    public String logout(HttpServletRequest request, HttpServletResponse response) {
        //覆盖当前当前用户cookie
        Cookie username = new Cookie("username", "");
        Cookie password = new Cookie("password", "");
        Cookie timestamp = new Cookie("timestamp","");
        username.setMaxAge(0);
        password.setMaxAge(0);
        timestamp.setMaxAge(0);
        response.addCookie(username);
        response.addCookie(password);
        response.addCookie(timestamp);
        //删除当前员工Session
        request.getSession().invalidate();
        return "redirect:/loginPage.html";
    }

    /**
     * 用于渲染添加用户界面
     *
     * @param adminUser 访问用户实体
     * @return ModelAndView
     */
    @RequestMapping("/addUserPage")
    public ModelAndView addUserPage(@SessionAttribute("user") User adminUser) {
        ModelAndView modelAndView = new ModelAndView();
        if (adminUser.getType() != 0)
            modelAndView.setViewName("redirect:/401Page.html");
        else
            modelAndView.setViewName("addUser");
        return modelAndView;
    }

    /**
     * 用于管理员添加用户
     *
     * @param instanceId 实例id
     * @param adminUser  管理员用户实体
     * @param user       添加用户实体
     * @return AjaxResponse
     */
    @RequestMapping("/addUserFromAdmin")
    @ResponseBody
    public AjaxResponse addUserFromAdmin(@SessionAttribute long instanceId, @SessionAttribute("user") User adminUser, @RequestBody User user) throws CustomException {
        if (adminUser.getType() != 0) {
            //添加用户非管理员
            throw new CustomException(CustomExceptionType.OPERATION_NOT_ALLOW, "非管理员无添加用户权限");
        }
        userService.add(user.getUsername(), user.getPassword(), user.getType(), instanceId);
        return AjaxResponse.success();
    }

    /**
     * 用于注册新实例
     *
     * @param user 用户实体/
     * @return AjaxResponse
     */
    @RequestMapping("/register")
    @ResponseBody
    public AjaxResponse addInstance(@RequestBody User user) throws CustomException {
        userService.addInstance(user);
        return AjaxResponse.success();
    }

    /**
     * 用于渲染用户管理页面
     *
     * @param instanceId 实例id
     * @return ModelAndView
     */
    @RequestMapping("/userData")
    public ModelAndView userData(@SessionAttribute long instanceId, @SessionAttribute("user") User adminUser) {
        ModelAndView modelAndView = new ModelAndView();
        if (adminUser.getType() != 0)
            modelAndView.setViewName("redirect:/401Page.html");
        else {
            List<User> userList = userService.getList(instanceId);
            modelAndView.addObject("userList", userList);
            modelAndView.setViewName("userManager");
        }
        return modelAndView;
    }

    /**
     * 用于停用用户账户
     *
     * @param instanceId 实例id
     * @param adminUser  管理员实体类
     * @param userId     用户id
     * @return AjaxResponse
     * @throws CustomException 当访问者非管理员，当无对应用户，账户已停用时抛出该异常
     */
    @RequestMapping("/suspendUser")
    @ResponseBody
    public AjaxResponse suspendUser(@SessionAttribute long instanceId, @SessionAttribute("user") User adminUser, long userId) throws CustomException {
        if (adminUser.getType() != 0) {
            //添加用户非管理员
            throw new CustomException(CustomExceptionType.OPERATION_NOT_ALLOW, "非管理员无管理权限");
        }
        if (userId == adminUser.getId()) {
            //停用自己
            throw new CustomException(CustomExceptionType.OPERATION_NOT_ALLOW, "不允许停用自身账户");
        }
        userService.suspendUser(instanceId, userId);
        return AjaxResponse.success();
    }

    /**
     * 用于启用用户
     *
     * @param instanceId 实例id
     * @param adminUser  管理员实体
     * @param userId     启用用户id
     * @return AjaxResponse
     * @throws CustomException 当访问者非管理员，当无对应用户，账户已启用时抛出该异常
     */
    @RequestMapping("/activeUser")
    @ResponseBody
    public AjaxResponse activeUser(@SessionAttribute long instanceId, @SessionAttribute("user") User adminUser, long userId) throws CustomException {
        if (adminUser.getType() != 0) {
            //访问用户非管理员
            throw new CustomException(CustomExceptionType.OPERATION_NOT_ALLOW, "非管理员无管理权限");
        }
        userService.activeUser(instanceId, userId);
        return AjaxResponse.success();
    }

    /**
     * 用于渲染用户详情页面
     *
     * @param instanceId 实例id
     * @param adminUser  管理员实体
     * @param id         用户id
     * @return ModelAndView
     */
    @RequestMapping("/detail")
    public ModelAndView detail(@SessionAttribute long instanceId, @SessionAttribute("user") User adminUser, long id) {
        ModelAndView modelAndView = new ModelAndView();
        if (adminUser.getType() != 0)
            modelAndView.setViewName("redirect:/401Page.html");
        else {
            modelAndView.setViewName("changeUser");
            User user = userService.get(instanceId, id);
            if (user == null) {
                modelAndView.setViewName("redirect:/401Page.html");
            } else {
                modelAndView.addObject("user", user);
            }
        }
        return modelAndView;
    }

    /**
     * 用于修改用户账户类型
     *
     * @param instanceId 实例id
     * @param adminUser  管理员实体
     * @param id         用户id
     * @param type       修改类型
     * @return AjaxResponse
     * @throws CustomException 当访问者非管理员，试图修改自身账户类型，用户不存在，用户类型不合法时抛出该异常
     */
    @PostMapping("/updateType")
    @ResponseBody
    public AjaxResponse changeType(@SessionAttribute long instanceId, @SessionAttribute("user") User adminUser, long id, int type) throws CustomException {
        if (adminUser.getType() != 0) {
            //访问人非管理员
            throw new CustomException(CustomExceptionType.OPERATION_NOT_ALLOW, "非管理员不允许调整用户类型");
        }
        if (adminUser.getId() == id) {
            //修改自身类型
            throw new CustomException(CustomExceptionType.OPERATION_NOT_ALLOW, "不允许修改自身账户类型");
        }
        userService.changeType(instanceId, id, type);
        return AjaxResponse.success();
    }

    /**
     * 用于修改账户密码
     *
     * @param instanceId 实例id
     * @param adminUser  管理员实体
     * @param id         用户id
     * @param password   修改密码
     * @return AjaxResponse
     * @throws CustomException 当访问者非管理员，用户不存在时抛出该异常
     */
    @PostMapping("/updatePassword")
    @ResponseBody
    public AjaxResponse changePasswordFromAdmin(@SessionAttribute long instanceId, @SessionAttribute("user") User adminUser, long id, String password) throws CustomException {
        if (adminUser.getType() != 0) {
            //访问人非管理员
            throw new CustomException(CustomExceptionType.OPERATION_NOT_ALLOW, "非管理员不允许调整用户类型");
        }
        userService.changePasswordFromAdmin(instanceId, id, password);
        return AjaxResponse.success();
    }


}
